package org.desktop.web.client.users.grid;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.desktop.web.client.gui.models.APagingGrid;
import org.desktop.web.client.gui.models.AbstractWindowForm.OperationType;
import org.desktop.web.client.user.UserService;
import org.desktop.web.client.user.UserServiceAsync;
import org.desktop.web.client.user.form.UserFormWindow;
import org.desktop.web.client.users.proxy.RpcUsersProxy;
import org.desktop.web.client.util.service.ReflectionService;
import org.desktop.web.client.util.service.ReflectionServiceAsync;
import org.desktop.web.shared.domain.entities.Role;
import org.desktop.web.shared.domain.entities.User;
import org.desktop.web.shared.domain.user.bean.UserProperties;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.cell.core.client.form.CheckBoxCell;
import com.sencha.gxt.core.client.dom.XElement;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.loader.FilterPagingLoadConfig;
import com.sencha.gxt.widget.core.client.event.CellClickEvent;
import com.sencha.gxt.widget.core.client.event.CellClickEvent.CellClickHandler;
import com.sencha.gxt.widget.core.client.event.RowDoubleClickEvent;
import com.sencha.gxt.widget.core.client.event.RowDoubleClickEvent.RowDoubleClickHandler;
import com.sencha.gxt.widget.core.client.form.CheckBox;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.editing.GridEditing;
import com.sencha.gxt.widget.core.client.grid.editing.GridInlineEditing;
import com.sencha.gxt.widget.core.client.info.Info;

public class UsersGrid extends
		APagingGrid<User, FilterPagingLoadConfig, UserProperties> {

	private static final UserServiceAsync userService = GWT
			.create(UserService.class);

	/**
	 * Serve per recuperare quelle colonne che necessitano di essere editate.
	 */
	private Map<String, ColumnConfig<User, Boolean>> checkColumns = new HashMap<String, ColumnConfig<User, Boolean>>();

	public UsersGrid(int pageSize, APagingGrid<?, ?, ?> childGrid,
			boolean remoteSort, APagingGrid<?, ?, ?> parent) {
		super(pageSize, childGrid, remoteSort, parent);

	}

	public UsersGrid(int pageSize, APagingGrid<?, ?, ?> childGrid,
			boolean remoteSort) {
		super(pageSize, childGrid, remoteSort);

	}

	public UsersGrid(int pageSize, APagingGrid<?, ?, ?> parent) {
		super(pageSize, parent);

	}

	public UsersGrid(int pageSize, boolean remoteSort,
			APagingGrid<?, ?, ?> parent) {
		super(pageSize, remoteSort, parent);

	}

	public UsersGrid(int pageSize) {
		super(pageSize);

	}

	@Override
	public UserProperties getPropertyAccess() {
		return GWT.create(UserProperties.class);
	}

	@Override
	public void initProxy() {
		setRpcProxy(new RpcUsersProxy());
	}

	@Override
	public List<ColumnConfig<User, ?>> getColumnsConfig() {
		
		UserProperties properties = getPropertyAccess();
		ColumnConfig<User, String> login = new ColumnConfig<User, String>(
				properties.login(), 100, "Login");

		ColumnConfig<User, Role> role = new ColumnConfig<User, Role>(
				properties.role(), 200, "Role");
		role.setCell(new AbstractCell<Role>() {

			@Override
			public void render(com.google.gwt.cell.client.Cell.Context context,
					Role r, SafeHtmlBuilder html) {
				html.appendHtmlConstant(r.getCodRole())
						.appendHtmlConstant(" - ")
						.appendHtmlConstant(r.getDescRole());
			}
		});

		ColumnConfig<User, Boolean> locked = new ColumnConfig<User, Boolean>(
				properties.locked(), 100, "Locked");

		locked.setCell(new UsersCheckBoxCell(getStore(), "locked"));

		ColumnConfig<User, Boolean> firstLogin = new ColumnConfig<User, Boolean>(
				properties.firstLogin(), 100, "First login");
		firstLogin.setCell(new UsersCheckBoxCell(getStore(), "firstLogin"));

		checkColumns.put("FIRST_LOGIN", firstLogin);


		List<ColumnConfig<User, ?>> cc = new ArrayList<ColumnConfig<User, ?>>();
		// cc.add(nameColumn);
		cc.add(login);
		cc.add(role);
		cc.add(locked);
		cc.add(firstLogin);
		return cc;
	}

	@Override
	public ModelKeyProvider<? super User> key() {
		// TODO Auto-generated method stub
		return getPropertyAccess().key();
	}

	@Override
	public Widget asWidget() {
		// TODO Auto-generated method stub

		super.asWidget();
		GridEditing<User> editing = new GridInlineEditing<User>(getGrid());
		ColumnConfig<User, Boolean> firstLogin = checkColumns
				.get("FIRST_LOGIN");
		CheckBox cb = new CheckBox();
		cb.addValueChangeHandler(new ValueChangeHandler<Boolean>() {

			@Override
			public void onValueChange(ValueChangeEvent<Boolean> arg0) {
				Info.display("", arg0 + "");

			}
		});
		editing.addEditor(firstLogin, cb);
		final UsersGrid _this_ = this;
		//doppio click sulla riga
		getGrid().addRowDoubleClickHandler(new RowDoubleClickHandler() {
			
			@Override
			public void onRowDoubleClick(RowDoubleClickEvent event) {
				
				UserFormWindow ufw = new UserFormWindow( OperationType.UPDATE,_this_);
				ufw.init();
				ufw.show();
				
			}
		});
		
		return getGrid();
	}
	
	static class UserMio extends JavaScriptObject {
		
		protected UserMio(){}
		public final native String getLogin() /*-{
			return this.login;
		}-*/;
	}

	@Override
	public CellClickHandler getCellClickHandler() {
		// TODO Auto-generated method stub

		return new CellClickHandler() {

			@Override
			public void onCellClick(CellClickEvent event) {
			}
		};
	}


	class UsersCheckBoxCell extends CheckBoxCell {

		ListStore<User> store;
		boolean clicked = false;

		String propertyName;
		
		ReflectionServiceAsync reflectionService;

		public UsersCheckBoxCell(ListStore<User> store, String propertyName) {
			super();
			this.store = store;
			this.propertyName = propertyName;
			this.reflectionService=GWT.create(ReflectionService.class);
		}

		@Override
		public void render(Context context, Boolean value, SafeHtmlBuilder sb) {
			// TODO Auto-generated method stub
			super.render(context, value, sb);
			if (clicked) {
				User user = this.store.get(context.getIndex());
				// converto lo user in un json. Questo mi permette di modificare
				// l'oggetto basandomi sul valore di propertyName.
				// questo perchè in gwt non è possibile usare la reflection.
				// Retrieve the AutoBean controller
				reflectionService.setProperty(user, propertyName, value, boolean.class.getName(), new AsyncCallback<Serializable>() {
					@Override
					public void onSuccess(Serializable user) {
						userService.update(Cookies.getCookie("token"),user,new AsyncCallback<Boolean>() {

							@Override
							public void onFailure(Throwable arg0) {
								// TODO Auto-generated method stub
								
							}

							@Override
							public void onSuccess(Boolean result) {
								// TODO Auto-generated method stub
								if(result){
									Info.display("Il campo è stato aggiornato","");
								}
							}
						});
					}
					
					@Override
					public void onFailure(Throwable arg0) {
						// TODO Auto-generated method stub
						
					}
				});
				clicked = false;
			}
		}

		@Override
		protected void onMouseDown(XElement parent, NativeEvent event) {
			// TODO Auto-generated method stub
			clicked = true;
			XElement e = event.getEventTarget().cast();
			Info.display("", e.getPropertyString("name"));
			super.onMouseDown(parent, event);
		}

	}
}
